﻿using System;
using Framework.Core.Cache;
using Framework.Core.Reflection;
using Rhino.Mocks;
using Xunit;

namespace Framework.Tests.Core.Cache
{
    extern alias castlecore;

    public class CacheKeyProviderTest
    {
        private readonly IHashProvider hashProviderMock;
        private readonly castlecore::Castle.DynamicProxy.IInvocation invocationMock;
        private readonly MockRepository mockRepository;
        private readonly ICacheKeyBuilder target;

        public CacheKeyProviderTest()
        {
            mockRepository = new MockRepository();
            invocationMock = mockRepository.StrictMock<castlecore::Castle.DynamicProxy.IInvocation>();
            hashProviderMock = mockRepository.StrictMock<IHashProvider>();
            target = new CacheKeyBuilder(hashProviderMock);
        }

        [Fact]
        public void Should_return_hascode_for_value_type()
        {
            var type = typeof (IPouet);
            var methodInfo = type.GetMethod("Get");
            invocationMock.Expect(x => x.Method).Return(methodInfo).Repeat.Twice();
            var arguments = new object[] {"pouet", 1, true};
            invocationMock.Expect(x => x.Arguments).Return(arguments).Repeat.Any();

            var i = 0;
            foreach (var argument in arguments)
            {
                var a = argument;
                hashProviderMock.Expect(x => x.Create(a)).Return(i++);
            }

            var expected = string.Format("{0} {1} {2}(System.String 0, System.Int32 1, System.Boolean 2)",
                                         methodInfo.Module.Assembly.FullName, methodInfo.DeclaringType, methodInfo.Name);

            Console.WriteLine(expected);

            mockRepository.ReplayAll();
            var actual = target.Build(new MethodFactory().Create(invocationMock));
            Assert.Equal(expected, actual);
            mockRepository.ReplayAll();
        }

        private interface IPouet
        {
            string Get(string a, int b, bool c);
        }
    }
}